package com.hospital.wx.service.Impl;

import cn.hutool.core.date.DateUtil;
import com.hospital.wx.dao.PatientUserDao;
import com.hospital.wx.dao.PatientUserInfoDao;
import com.hospital.wx.pojo.PatientUser;
import com.hospital.wx.service.PatientUserService;
import com.hospital.wx.util.WxAppUtil;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

@Service
@Slf4j
public class PatientUserServiceImpl implements PatientUserService {

    @Autowired
    private WxAppUtil wxAppUtil;

    @Autowired
    private PatientUserDao patientUserDao;

    @Autowired
    private PatientUserInfoDao patientUserInfoDao;

    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.access-key}")
    private String accessKey;
    @Value("${minio.secret-key}")
    private String secretKey;
    @Value("${minio.bucket-name}")
    private String bucketName;

    @Override
    @Transactional
    public Map<String, Object> loginOrRegister(String code, String nickname, String photo, String sex) {
        // 获取 openId
        String openId = wxAppUtil.getOpenId(code);

        // 检查用户是否存在
        Integer id = patientUserDao.existsUserByOpenId(openId);

        // 如果用户未注册，进行注册流程
        if (id == null) {
            id = registerNewUser(openId, nickname, photo, sex);
            return buildResultMap("注册成功", openId, id, photo, nickname);
        } else {
            // 如果用户已存在，返回登录成功
            return buildResultMap("登陆成功", openId, id, photo, nickname);
        }
    }

    // 注册新用户的逻辑
    private Integer registerNewUser(String openId, String nickname, String photo, String sex) {
        PatientUser entity = new PatientUser();
        entity.setOpenId(openId);
        entity.setNickname(nickname);
        entity.setPhoto(photo);
        entity.setSex(sex);
        entity.setStatus((byte) 1);

        // 保存新用户信息到数据库
        patientUserDao.insert(entity);

        // 返回新用户的 ID
        return entity.getId();
    }

    // 构建返回结果 Map
    private Map<String, Object> buildResultMap(String msg, String openId, Integer id, String photo, String nickname) {
        Map<String, Object> result = new HashMap<>();
        result.put("msg", msg);
        result.put("id", id);
        result.put("photo", photo);
        result.put("nickname", nickname);
        result.put("openId", openId);

        // 获取用户的电话信息，如果存在则返回
//        String tel = patientUserInfoDao.selectTelById(id);
//        if (tel != null && tel.length() > 0) {
//            result.put("tel", tel);
//        }
        return result;
    }


    /*
    * 上传头像
    * */

    @Override
    @Transactional
    public String uploadAvatar(MultipartFile file) {
        try {
            // 1. 基本验证
            if (file == null || file.isEmpty()) {
                throw new IllegalArgumentException("上传的文件为空");
            }

            // 2. 获取文件扩展名
            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null) {
                throw new IllegalArgumentException("文件名不能为空");
            }

            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();

            // 3. 验证文件格式
            List<String> supportedFormats = Arrays.asList(".png", ".jpg", ".jpeg");
            if (!supportedFormats.contains(fileExtension)) {
                throw new IllegalArgumentException("不支持的文件格式，仅支持 PNG、JPG、JPEG 格式");
            }

            // 4. 生成文件名
            String date = DateUtil.format(new Date(), "yyyyMMdd") + "/";
            String filename = date + "blog-" + UUID.randomUUID().toString().replace("-", "") + fileExtension;

            // 5. 设置正确的 ContentType
            String contentType;
            switch (fileExtension) {
                case ".png":
                    contentType = "image/png";
                    break;
                case ".jpg":
                case ".jpeg":
                    contentType = "image/jpeg";
                    break;
                default:
                    contentType = file.getContentType();
            }

            // 6. 上传到 MinIO
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(endpoint)
                    .credentials(accessKey, secretKey)
                    .build();

            // 检查并创建 bucket
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                // 设置 bucket 策略（如果需要公开访问）
                setBucketPolicy(minioClient, bucketName);
            }

            // 上传文件
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(filename)
                            .stream(file.getInputStream(), file.getSize(), -1)
                            .contentType(contentType)
                            .build()
            );

            log.info("文件上传成功: {}", filename);

            // 7. 返回访问URL
            return endpoint + "/" + bucketName + "/" + filename;

        } catch (Exception e) {
            log.error("文件上传失败", e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }

    // 设置 bucket 策略的辅助方法
    private void setBucketPolicy(MinioClient minioClient, String bucketName) throws Exception {
        String policy = """
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": "*",
                    "Action": ["s3:GetObject"],
                    "Resource": ["arn:aws:s3:::%s/*"]
                }
            ]
        }
        """.formatted(bucketName);

        minioClient.setBucketPolicy(
                SetBucketPolicyArgs.builder()
                        .bucket(bucketName)
                        .config(policy)
                        .build()
        );
    }

    @Override
    @Transactional
    public int updatePatientUser(Map map) {
        if (!map.isEmpty()) {
            return patientUserDao.updatePatientUser(map);
        }else{
            return 0;
        }
    }

    @Override
    public int selectAppointmentCount() {
        return patientUserDao.selectAppointmentCount();
    }
}
